<?php
namespace app\common\model;

use think\model\concern\SoftDelete;

class CheckClock extends Base
{
    use SoftDelete;
    protected $createTime = false;
    protected $deleteTime = 'delete_time';

    /**
     * 获取打卡类型（1=上班打卡，2=下班打卡）
     * @param int    $userId 员工ID
     * @param string $clockWifi 打卡Wifi
     * @param string $bssid 打卡Wifi bssid
     * @param bool   $isClockOut 是否外勤打卡
     */
    public static function getClockType($userId = 0, $clockWifi = '', $bssid = '', $isClockOut = 0)
    {
        if(self::isWifi($clockWifi, $bssid) === false && $isClockOut == 0) return false;
        $info = self::where('user_id', $userId)->whereDay('create_time')->order('create_time DESC')->find();

        $checkRuleInfo = CheckRule::getFind(['id' => User::getVal(['id' => $userId], 'check_clock_id')]);

        /** 当前秒数 */
        $time = time() - strtotime(date('Y-m-d', time()));

        if(!$info && $time >= $checkRuleInfo['end_time']) return 2;

        if(!$info) return 1;
        if($info['clock_type'] == 1) return 2;
        if($info['clock_type'] == 2) return $info['id'];
        
        return false;
    }

    /**
     * 获取打卡状态
     * @param int    $userId 员工ID
     * @param int    $type 打卡类型(1=上班卡，2=下班卡)
     */
    public static function getClockStatus($userId = 0, $type = 0)
    {
        $userInfo = User::getFind(['id' => $userId]);
        if($userInfo === false) return ['status' => -1, 'data' => -1001, 'msg' => '用户不存在'];
        if($userInfo['check_clock_id'] == 0) return ['status' => -1, 'data' => -1002, 'msg' => '请先设置考勤规则'];

        $checkRuleInfo = CheckRule::getFind(['id' => $userInfo['check_clock_id']]);
        if($checkRuleInfo === false) return ['status' => -1, 'data' => -1003, 'msg' => '考勤规则不存在'];

        /** 当前秒数 */
        $time = time() - strtotime(date('Y-m-d', time()));

        if($type == 1){
            $ruleTime = $checkRuleInfo['start_time'];
            if($time > $ruleTime + 60) return ['status' => 2, 'data' => $time - $ruleTime, 'msg' => ''];
        }else if($type == 2){
            $ruleTime = $checkRuleInfo['end_time'];
            if($time < $ruleTime) return ['status' => 3, 'data' => $ruleTime - $time, 'msg' => ''];
        }else{
            return ['status' => 1, 'data' => -1004, 'msg' => '未知错误'];
        }

        return ['status' => 1, 'data' => 0, 'msg' => ''];
    }

    /**
     * 打卡WiFi是否正确
     * @param string $wifiName 打卡Wifi
     * @param string $bssid 打卡Wifi bssid
     */
    public static function isWifi($wifiName = '', $bssid = '')
    {
        if(empty($wifiName) || empty($bssid)) return false;

        $system = getSystem();

        // $wifiArr  = explode(',', $system['clock_wifi']);
        $bssidArr = explode(',', $system['clock_wifi_bssid']);

        $bssid = substr($bssid, 0, 11);

        // if(in_array($wifiName, $wifiArr) === false) return false;
        if(in_array($bssid, $bssidArr) === false) return false;

        return true;
    }

    /**
     * 计算请假时长
     * @param int $userId 员工ID
     * @param string $start_time 开始时间
     * @param string $end_time 结束时间
     * @param int    $type 类型（1=小时，2=半天，3=天）
     */
    public static function getLeaveTime($userId = 0, $start_time = 0, $end_time = 0, $type = 0)
    {
        if($userId == 0 || $start_time == 0 || $end_time == 0 || $type == 0) return ['status' => -1, 'data' => 0, 'msg' => '数据错误'];

        $userInfo = User::getFind(['id' => $userId]);
        if($userInfo === false) return ['status' => -1, 'data' => 0, 'msg' => '用户不存在'];
        if($userInfo['check_clock_id'] == 0) return ['status' => -1, 'data' => 0, 'msg' => '请先设置考勤规则'];

        $checkRuleInfo = CheckRule::getFind(['id' => $userInfo['check_clock_id']]);
        if($checkRuleInfo === false) return ['status' => -1, 'data' => 0, 'msg' => '考勤规则不存在'];

        /** 请假起止时间 */
        $startTime = strtotime($start_time);
        $endTime   = strtotime($end_time);

        if($endTime < $startTime) return ['status' => -1, 'data' => 0, 'msg' => '结束时间不能小于开始时间'];

        /** 请假的起止时间（当天的秒数） */
        $starDayTime = strtotime($start_time) - strtotime(date('Y-m-d', strtotime($start_time)));
        $endDayTime  = strtotime($end_time) - strtotime(date('Y-m-d', strtotime($end_time)));

        /** 考勤上下班时间 */
        $startRuleTime = $checkRuleInfo['start_time'];
        $endRuleTime   = $checkRuleInfo['end_time'];

        /** 中午休息起止时间 */
        $startRestTime = 12 * 60 * 60;
        $endRestTime   = 13 * 60 * 60 + 30 * 60;

        if($type == 1){
            if(date('Y-m-d', $startTime) == date('Y-m-d', $endTime)){  /** 请假时间同天的情况 */
                if($starDayTime < $startRuleTime) $starDayTime = $startRuleTime;
                if($endDayTime > $endRuleTime) $endDayTime = $endRuleTime;

                /** 全天假 */
                if($starDayTime < $startRestTime && $endDayTime <= $endRuleTime && $endDayTime > $startRestTime) return ['status' => 0, 'data' => ['duration' => 1, 'type' => 1], 'msg' => 'ok'];

                if(($starDayTime < $startRestTime && $endDayTime <= $startRestTime) 
                || $starDayTime >= $endRestTime && $endDayTime > $endRestTime
                ){  /** 上午或下午请假 */
                    if(($endDayTime - $starDayTime) >= 2 * 60 * 60){
                        return ['status' => 0, 'data' => ['duration' => 0.5, 'type' => 1], 'msg' => 'ok'];
                    }else{
                        return ['status' => 0, 'data' => ['duration' => secondToHours($endDayTime - $starDayTime), 'type' => 2], 'msg' => 'ok'];
                    }
                }else{  /** 跨午休请假 */
                    $leaveTime = ($startRestTime - $starDayTime) + ($endDayTime - $endRestTime);

                    if($leaveTime >= 2 * 60 * 60){
                        return ['status' => 0, 'data' => ['duration' => 0.5, 'type' => 1], 'msg' => 'ok'];
                    }else{
                        return ['status' => 0, 'data' => ['duration' => secondToHours($leaveTime), 'type' => 2], 'msg' => 'ok'];
                    }
                }
            }else{  /** 请假时间跨天的情况 */
                if($starDayTime < $startRuleTime) $starDayTime = $startRuleTime;
                if($endDayTime > $endRuleTime) $endDayTime = $endRuleTime;

                /** 请假天数 */
                $leaveDays = date('d', $endTime) - date('d', $startTime) - 1;

                $starDayTime < $startRestTime ? $leaveDays += 1 :  $leaveDays += 0.5;
                $endDayTime > $endRestTime ? $leaveDays += 1 :  $leaveDays += 0.5;

                return ['status' => 0, 'data' => ['duration' => $leaveDays, 'type' => 1], 'msg' => 'ok'];
            }
        }else if($type == 2){
            if($startTime == $endTime){
                $duration = 0.5;
            }else if(date('Y-m-d', $startTime) == date('Y-m-d', $endTime)){
                $duration = 1;
            }else{
                $startDuration = $endRuleTime - $starDayTime > 0 ? 0 : -0.5;
                $endDuration   = $endRuleTime - $endDayTime > 0 ? -0.5 : 0;
                $daysDuration  = floor((strtotime(date('Y-m-d', strtotime($end_time))) - strtotime(date('Y-m-d', strtotime($start_time)))) / 86400) + 1;

                $duration = $startDuration + $endDuration + $daysDuration;
            }

            return ['status' => 0, 'data' => $duration, 'msg' => 'ok'];
        }else if($type == 3){
            if($startTime == $endTime){
                $duration = 1;
            }else{
                $duration = floor(($endTime - $startTime) / 86400) + 1;
            }

            return ['status' => 0, 'data' => $duration, 'msg' => 'ok'];
        }else{
            return ['status' => -1, 'data' => 0, 'msg' => '数据错误'];
        }
    }

    /**
     * 每日记录
     * @param int     $userId 员工ID
     * @param string  $days 日期（年月）
     */
    public static function getCheckDays($userId = 0, $days = 0)
    {
        if($days == 0) $days = date('Y-m', time());
        list($year, $month) = explode('-', $days);

        $field = 'g_year, g_month, g_days, week, status';
        $list = Calendar::where(['g_year' => $year, 'g_month' => $month])->field($field)->order('g_days')->select();
        if($list->isEmpty()) return false;

        $userInfo = User::getFind(['id' => $userId], 'check_clock_id');

        foreach($list as &$info){
            $newDay = $info['g_year'] . '-' . $info['g_month'] . '-' . $info['g_days'];

            if(in_array($info['status'], [1 ,4]) !== false){
                $info['clock_rule'] = CheckRule::getCheckRule($userInfo['check_clock_id']);
                if(strtotime($newDay) > time()) continue;
            }else{
                $info['clock_rule'] = '休息';
                continue;
            }

            /** 打卡次数 */
            $clockNums = self::where(['user_id' => $userId])->whereDay('create_time', $newDay)->count();

            /** 工时 */
            $workTime = self::where(['user_id' => $userId, 'clock_type' => 2])->whereDay('create_time', $newDay)->Value('work_time');

            $info['clock_news'] = '共' . $clockNums . '次卡，工时' . secondToHours($workTime) . '小时';

            $info['start_time'] = [
                'time'   => '上班' . self::getClockTime($userId, 1, $newDay),
                'status' => self::getStatusDays($userId, 1, $newDay),
            ];

            $info['end_time'] = [
                'time'   => '下班' . self::getClockTime($userId, 2, $newDay),
                'status' => self::getStatusDays($userId, 2, $newDay),
            ];
        }

        return $list;
    }

    /**
     * 考勤统计的打卡状态
     * @param int     $userId 员工ID
     * @param int     $type 打卡类型(1=上班卡，2=下班卡)
     * @param string  $days 日期(格式：2021-11-30)
     * @return int    1 = 正常，2 = 迟到， 3 = 早退， 4 = 外勤， 5 = 缺卡， 6 = 请假
     */
    public static function getStatusDays($userId = 0, $type = 0, $days = '')
    {
        if($days == 0) $days = date('Y-m-d', time());

        $info = self::where(['user_id' => $userId, 'clock_type' => $type])->whereDay('create_time', $days)->find();

        if($info){
            if($info['is_out'] == 1) return 4;
            return $info['clock_status'];
        }

        if($days == '这里去查询下是不是请假了') return 6;
        return 5;
    }

    /**
     * 获取打卡时间
     * @param int $userId 员工ID
     * @param int $type 打卡类型(1=上班卡，2=下班卡)
     */
    public static function getClockTime($userId = 0, $type = 1, $days = 0)
    {
        if($days == 0) $days = date('Y-m-d', time());

        $time = self::where(['user_id' => $userId, 'clock_type' => $type])->whereDay('create_time', $days)->value('create_time');

        if(!$time) return '未打卡';
        return date('H:i', $time) . '已打卡';
    }

    /**
     * 计算工时
     * @param int $userId 员工ID
     */
    public static function getWorkTime($userId = 0)
    {
        $time = self::where(['user_id' => $userId, 'clock_type' => 1])->whereDay('create_time')->value('create_time');
        if(!$time) return 0;
        return time() - $time;
    }

    /**
     * 计算平均工时
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     */
    public static function getWorkTimeAvg($userId = 0, $days = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $workTime = self::where(['user_id' => $userId])->whereMonth('create_time', $days)->sum('work_time');

        $clockDayNum = self::getClockDays($userId, $days);

        if($clockDayNum <= 0) return 0;
        return round(secondToHours($workTime) / $clockDayNum, 1);
    }

    /**
     * 计算打卡天数
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     */
    public static function getClockDays($userId = 0, $days = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $startList = self::where(['user_id' => $userId, 'clock_type' => 1])->whereMonth('create_time', $days)->column('create_time');
        $endList   = self::where(['user_id' => $userId, 'clock_type' => 2])->whereMonth('create_time', $days)->column('create_time');

        $list = array_merge($startList, $endList);

        foreach($list as &$time){
            $time = date('Y-m-d', $time);
        }

        $newList = array_unique($list);
        return count($newList);
    }

    /**
     * 计算迟到次数
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     * @param int    $type 返回类型（0=文字描述, 1=记录，2=次数）
     */
    public static function getLateNums($userId = 0, $days = 0, $type = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $clockList = CheckClock::where(['user_id' => $userId, 'clock_status' => 2])->whereMonth('create_time', $days)->select();
        if($clockList->isEmpty()) return 0;

        $clockList = $clockList->toArray();
        if($type == 0) return count($clockList) . '次，共' . floor(array_sum(array_column($clockList, 'status_time')) / 60) . '分钟';
        if($type == 2) return count($clockList);

        $userInfo = User::getFind(['id' => $userId]);
        $checkRuleInfo = CheckRule::getFind(['id' => $userInfo['check_clock_id']]);

        $week = [1 => '星期一', 2 => '星期二', 3 => '星期三', 4 => '星期四', 5 => '星期五', 6 => '星期六', 0 => '星期日'];

        $lateDay = [];
        foreach($clockList as $info){
            $lateInfo['days'] = $info['create_time'] . '（' . $week[date('w', strtotime($info['create_time']))] . '）' . secondToHour($checkRuleInfo['start_time']);
            $lateInfo['time'] = '上班迟到' . secondToHourStr($info['status_time']);
            $lateDay[] = $lateInfo;
        }

        return $lateDay;
    }

    /**
     * 计算早退次数
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     * @param int    $isDay 是否日期记录
     */
    public static function getEarlyNums($userId = 0, $days = 0, $isDay = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $clockList = CheckClock::where(['user_id' => $userId, 'clock_status' => 3])->whereMonth('create_time', $days)->select();
        if($clockList->isEmpty()) return 0;

        $clockList = $clockList->toArray();
        if($isDay == 0) return count($clockList) . '次，共' . floor(array_sum(array_column($clockList, 'status_time')) / 60) . '分钟';

        $userInfo = User::getFind(['id' => $userId]);
        $checkRuleInfo = CheckRule::getFind(['id' => $userInfo['check_clock_id']]);

        $week = [1 => '星期一', 2 => '星期二', 3 => '星期三', 4 => '星期四', 5 => '星期五', 6 => '星期六', 7 => '星期日'];

        $earlyDay = [];
        foreach($clockList as $info){
            $earlyInfo['days'] = $info['create_time'] . '（' . $week[date('w', strtotime($info['create_time']))] . '）' . secondToHour($checkRuleInfo['start_time']);
            $earlyInfo['time'] = '下班早退' . secondToHourStr($info['status_time']);
            $earlyDay[] = $earlyInfo;
        }

        return $earlyDay;
    }

    /**
     * 统计缺卡次数或日期
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     * @param int    $isDay 是否日期记录
     */
    public static function getMissCardNums($userId = 0, $days = 0, $isDay = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $year  = date('Y', strtotime($days));
        $month = date('m', strtotime($days));

        $calendar = Calendar::getList(['g_year' => $year, 'g_month' => $month]);
        if($calendar === false) return 0;

        $userInfo = User::getFind(['id' => $userId]);
        $checkRuleInfo = CheckRule::getFind(['id' => $userInfo['check_clock_id']]);

        $nums = 0;
        $missCardDay = [];
        foreach($calendar as $info){
            if($info['status'] == 2 || $info['status'] == 3) continue;

            $nowsDay = $info['g_year'] . '-'. $info['g_month'] . '-' . $info['g_days'];

            if(strtotime($nowsDay) >= strtotime(date('Y-m-d', time()))) continue;

            $clockStart = CheckClock::where(['user_id' => $userId, 'clock_type' => 1])->whereDay('create_time', $nowsDay)->find();
            $clockEnd   = CheckClock::where(['user_id' => $userId, 'clock_type' => 2])->whereDay('create_time', $nowsDay)->find();
            if(!$clockStart && !$clockEnd) continue;
            if($clockStart && $clockEnd) continue;

            $week = [1 => '星期一', 2 => '星期二', 3 => '星期三', 4 => '星期四', 5 => '星期五', 6 => '星期六', 7 => '星期日'];

            if($isDay == 0){
                $nums++;
            }else{
                $content = $info['g_year'] . '-' . $info['g_month'] . '-' . $info['g_days'] . '（' . $week[$info['week']] . '）';

                if(!$clockStart){
                    $missCardInfo['days'] = $content . secondToHour($checkRuleInfo['start_time']);
                }else{
                    $missCardInfo['days'] = $content . secondToHour($checkRuleInfo['end_time']);
                }

                $missCardDay[] = $missCardInfo;
            }
        }

        if($isDay !== 0) return $missCardDay;
        return $nums;
    }

    /**
     * 统计旷工次数或日期
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     * @param int    $isDay 是否日期记录
     */
    public static function getWorkNeglectNums($userId = 0, $days = 0, $isDay = 0)
    {
        $year  = date('Y', strtotime($days));
        $month = date('m', strtotime($days));

        $calendar = Calendar::getList(['g_year' => $year, 'g_month' => $month]);
        if($calendar === false) return 0;

        $nums = 0;
        $workNeglectDay = [];
        foreach($calendar as $info){
            if($info['status'] == 2 || $info['status'] == 3) continue;

            $nowsDay = $info['g_year'] . '-'. $info['g_month'] . '-' . $info['g_days'];

            if(strtotime($nowsDay) >= strtotime(date('Y-m-d', time()))) continue;

            $clockInfo = CheckClock::where(['user_id' => $userId])->whereDay('create_time', $nowsDay)->find();
            if($clockInfo) continue;

            $week = [1 => '星期一', 2 => '星期二', 3 => '星期三', 4 => '星期四', 5 => '星期五', 6 => '星期六', 7 => '星期日'];

            $isLeave = ApplyLeave::where(['user_id' => $userId])->whereDay('start_time|end_time', $nowsDay)->value('id');

            if(!$isLeave){
                if($isDay == 0){
                    $nums++;
                }else{
                    $workNeglectInfo['days'] = $info['g_year'] . '-' . $info['g_month'] . '-' . $info['g_days'] . '（' . $week[$info['week']] . '）';
                    $workNeglectDay[] = $workNeglectInfo;
                }
            }
        }

        if($isDay !== 0) return $workNeglectDay;
        return $nums;
    }

    /**
     * 统计外勤次数或日期
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     * @param int    $isDay 是否日期记录
     */
    public static function getClockOutNums($userId = 0, $days = 0, $isDay = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $clockList = CheckClock::where(['user_id' => $userId, 'is_out' => 1])->whereDay('create_time', $days)->select();
        if(!$clockList) return 0;
        if($isDay == 0) return count($clockList->toArray());

        $userInfo = User::getFind(['id' => $userId]);
        $checkRuleInfo = CheckRule::getFind(['id' => $userInfo['check_clock_id']]);

        $week = [1 => '星期一', 2 => '星期二', 3 => '星期三', 4 => '星期四', 5 => '星期五', 6 => '星期六', 7 => '星期日'];

        $workOutDay = [];

        foreach($clockList as $info){
            $content = $info['create_time'] . '（' . $week[date('w', strtotime($info['create_time']))] . '）';

            if($info['clock_type'] == 1){
                $workOutInfo['days'] = $content . secondToHour($checkRuleInfo['start_time']);
            }else{
                $workOutInfo['days'] = $content . secondToHour($checkRuleInfo['end_time']);
            }

            $workOutInfo['address'] = $info['clock_address'];
            $workOutDay[] = $workOutInfo;
        }

        return $workOutDay;
    }

    /**
     * 统计加班时长或日期
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     * @param int    $isDay 是否日期记录
     */
    public static function getWorkOverNums($userId = 0, $days = 0, $isDay = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $workOverList = ApplyWorkOver::where(['user_id' => $userId, 'status' => 2])->whereDay('create_time', $days)->select();
        if(!$workOverList) return 0;
        if($isDay == 0) return array_sum(array_column($workOverList->toArray(), 'duration'));

        $workOverDay = [];
        foreach($workOverList as $info){
            $workOverInfo['days'] = date('Y-m-d H:i', $info['start_time']) . ' -- ' . date('Y-m-d H:i', $info['end_time']);
            $workOverInfo['time'] = array_sum(array_column($workOverList->toArray(), 'duration'));
            $workOverDay[] = $workOverInfo;
        }

        return $workOverDay;
    }

    /**
     * 获取休息记录
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     * @param int    $isDay 是否日期记录
     */
    public static function getRestNums($userId = 0, $days = 0, $isDay = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $year  = date('Y', strtotime($days));
        $month = date('m', strtotime($days));

        $calendar = Calendar::getList(['g_year' => $year, 'g_month' => $month]);
        if($calendar === false) return 0;

        $nums = 0;
        $restDay = [];
        foreach($calendar as $info){
            $nowsDay = $info['g_year'] . '-'. $info['g_month'] . '-' . $info['g_days'];
            if(strtotime($nowsDay) >= strtotime(date('Y-m-d', time()))) continue;

            if($info['status'] == 1 || $info['status'] == 4) continue;

            $week = [1 => '星期一', 2 => '星期二', 3 => '星期三', 4 => '星期四', 5 => '星期五', 6 => '星期六', 7 => '星期日'];

            if($isDay == 0){
                $nums++;
            }else{
                $restInfo['days'] = $info['g_year'] . '-' . $info['g_month'] . '-' . $info['g_days'] . '（' . $week[$info['week']] . '）';
                $restDay[] = $restInfo;
            }
        }

        if($isDay !== 0) return $restDay;
        return $nums;
    }

    /**
     * 获取每日工时记录
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     */
    public static function getWorkTimeRecord($userId = 0, $days = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $year  = date('Y', strtotime($days));
        $month = date('m', strtotime($days));

        $calendar = Calendar::getList(['g_year' => $year, 'g_month' => $month]);
        if($calendar === false) return [];

        $workTimeDay = [];
        foreach($calendar as $info){
            if($info['status'] == 2 || $info['status'] == 3) continue;

            $nowsDay = $info['g_year'] . '-'. $info['g_month'] . '-' . $info['g_days'];

            if(strtotime($nowsDay) >= strtotime(date('Y-m-d', time() + 86400))) continue;

            $clockStart = CheckClock::where(['user_id' => $userId, 'clock_type' => 1])->whereDay('create_time', $nowsDay)->find();
            $clockEnd   = CheckClock::where(['user_id' => $userId, 'clock_type' => 2])->whereDay('create_time', $nowsDay)->find();
            if(!$clockStart && !$clockEnd) continue;

            $week = [1 => '星期一', 2 => '星期二', 3 => '星期三', 4 => '星期四', 5 => '星期五', 6 => '星期六', 7 => '星期日'];

            $workTimeInfo['days'] = $info['g_year'] . '-' . $info['g_month'] . '-' . $info['g_days'] . '（' . $week[$info['week']] . '）';
            $workTimeInfo['time'] = 0;

            if($clockStart && $clockEnd) $workTimeInfo['time'] = secondToHours($clockEnd['work_time']);

            $workTimeDay[] = $workTimeInfo;
        }

        return $workTimeDay;
    }

    /**
     * 获取出勤记录
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     */
    public static function getWorkDaysRecord($userId = 0, $days = 0)
    {
        if($days == 0) $days = date('Y-m', $days);

        $year  = date('Y', strtotime($days));
        $month = date('m', strtotime($days));

        $calendar = Calendar::getList(['g_year' => $year, 'g_month' => $month]);
        if($calendar === false) return [];

        $workTimeDay = [];
        foreach($calendar as $info){
            if($info['status'] == 2 || $info['status'] == 3) continue;

            $nowsDay = $info['g_year'] . '-'. $info['g_month'] . '-' . $info['g_days'];

            if(strtotime($nowsDay) >= strtotime(date('Y-m-d', time() + 86400))) continue;

            $clockStart = CheckClock::where(['user_id' => $userId, 'clock_type' => 1])->whereDay('create_time', $nowsDay)->find();
            $clockEnd   = CheckClock::where(['user_id' => $userId, 'clock_type' => 2])->whereDay('create_time', $nowsDay)->find();
            if(!$clockStart && !$clockEnd) continue;

            $week = [1 => '星期一', 2 => '星期二', 3 => '星期三', 4 => '星期四', 5 => '星期五', 6 => '星期六', 7 => '星期日'];

            $workTimeInfo['days'] = $info['g_year'] . '-' . $info['g_month'] . '-' . $info['g_days'] . '（' . $week[$info['week']] . '）';
            $workTimeInfo['time'] = 1;

            $workTimeDay[] = $workTimeInfo;
        }

        return $workTimeDay;
    }

    /**
     * 获取加班时长
     * @param int    $userId 员工ID
     * @param string $days 日期（年月）
     */
    public static function getWorkOverNum($userId = 0, $days = 0)
    {
        return ApplyWorkOver::getSum(['user_id' => $userId, 'status' => 2], 'duration');
    }

    /**
     * 获取用户某天的打卡状态
     * @param int $userId  员工ID
     * @param string $days  日期（年-月-日）
     */
    public static function getUserCheckStatus($userId = 0, $days = '', $dayStatus = 0, $startTime, $endTime)
    {
        if(strtotime($days) > time()) return '';

        /** 上班打卡记录 */
        $checkFst = self::where(['user_id' => $userId, 'clock_type' => 1])->field('clock_status, is_out')->whereDay('create_time', $days)->find();
        
        /** 下班打卡记录 */
        $checkSec = self::where(['user_id' => $userId, 'clock_type' => 2])->field('clock_status, is_out')->whereDay('create_time', $days)->find();

        /** 是否休息日 */
        $isRest = in_array($dayStatus, [2, 3]) ? 1 : 0;
        $isRestText = $isRest ? '休息打卡' : '';

        if($checkFst && $checkSec){
            if($checkFst['clock_status'] == 1 && $checkSec['clock_status'] == 1){
                if($checkFst['is_out'] == 1 && $checkSec['is_out'] == 1){
                    return $isRestText . '外勤';
                }else if($checkFst['is_out'] == 1 && $checkSec['is_out'] == 0){
                    return $isRestText . '上班外勤';
                }else if($checkFst['is_out'] == 0 && $checkSec['is_out'] == 1){
                    return $isRestText . '下班外勤';
                }

                if($isRest) return '休息打卡';

                return '正常';
            }else if($checkFst['clock_status'] == 2 && $checkSec['clock_status'] == 1){
                if($checkFst['is_out'] == 1 && $checkSec['is_out'] == 1){
                    return $isRestText . '外勤 上班迟到';
                }else if($checkFst['is_out'] == 1 && $checkSec['is_out'] == 0){
                    return $isRestText . '上班外勤迟到';
                }else if($checkFst['is_out'] == 0 && $checkSec['is_out'] == 1){
                    return $isRestText . '上班迟到 下班外勤';
                }

                return $isRestText . '上班迟到';
            }else if($checkFst['clock_status'] == 1 && $checkSec['clock_status'] == 3){
                if($checkFst['is_out'] == 1 && $checkSec['is_out'] == 1){
                    return $isRestText . '外勤 下班早退';
                }else if($checkFst['is_out'] == 1 && $checkSec['is_out'] == 0){
                    return $isRestText . '上班外勤 下班早退';
                }else if($checkFst['is_out'] == 0 && $checkSec['is_out'] == 1){
                    return $isRestText . '下班外勤早退';
                }

                return $isRestText . '下班早退';
            }else if($checkFst['clock_status'] == 2 && $checkSec['clock_status'] == 3){
                if($checkFst['is_out'] == 1 && $checkSec['is_out'] == 1){
                    return $isRestText . '外勤 上班迟到 下班早退';
                }else if($checkFst['is_out'] == 1 && $checkSec['is_out'] == 0){
                    return $isRestText . '上班外勤迟到 下班早退';
                }else if($checkFst['is_out'] == 0 && $checkSec['is_out'] == 1){
                    return $isRestText . '上班迟到 下班外勤早退';
                }

                return $isRestText . '上班迟到 下班早退';
            }
        }else if(!$checkFst && $checkSec){
            $checkWork = '';

            /** 补卡记录 */
            $missCardInfo = ApplyMissCard::where(['user_id' => $userId, 'clock_type' => 1])->whereDay('times', $days)->value('id');
            if($missCardInfo) $checkWork = '上班补卡';

            /** 请假记录 */
            $leaveInfo = ApplyLeave::where(['user_id' => $userId])->whereDay('start_time', $days)->value('id');
            if($leaveInfo) $checkWork = '上午请假';

            if(!$missCardInfo && !$leaveInfo) $checkWork = '上班缺卡';

            if($checkSec['clock_status'] == 3) $checkWork .= ' 下班早退';
            if($checkSec['clock_status'] == 3 && $checkSec['is_out'] == 1) $checkWork .= ' 下班外勤早退';

            return $isRestText . $checkWork;
        }else if($checkFst && !$checkSec){
            $checkWork = '';

            if($checkFst['clock_status'] == 2) $checkWork = '上班迟到';
            if($checkFst['clock_status'] == 2 && $checkFst['is_out'] == 1) $checkWork = '上班外勤迟到';

            /** 补卡记录 */
            $missCardInfo = ApplyMissCard::where(['user_id' => $userId, 'clock_type' => 2])->whereDay('times', $days)->value('id');
            if($missCardInfo) $checkWork .= ' 下班补卡';

            /** 请假记录 */
            $leaveInfo = ApplyLeave::where(['user_id' => $userId])->whereDay('end_time', $days)->value('id');
            if($leaveInfo) $checkWork .= ' 下午请假';

            if(!$missCardInfo && !$leaveInfo) $checkWork .= ' 下班缺卡';

            return $isRestText . $checkWork;
        }else{
            /** 请假记录 */
            $leaveInfo = ApplyLeave::where([
                ['user_id', '=', $userId], 
                ['start_time', '<=', strtotime($days) + $startTime],
                ['end_time', '>=', strtotime($days) + $endTime],
                ])->value('id');
            
            if($leaveInfo) return '请假';
            if($isRest) return '休息';
            return '旷工';
        }

        return '异常';
    }

    /**
     * 获取请假时长
     * @param int    $userId 员工ID
     * @param string $days 日期（年-月）
     */
    public static function getLeaveDuration($userId = 0, $days = 0)
    {
        $dayNum  = ApplyLeave::where(['user_id' => $userId, 'status' => 2, 'duration_type' => 1])->whereMonth('start_time|end_time', $days)->sum('duration');
        $duraNum = ApplyLeave::where(['user_id' => $userId, 'status' => 2, 'duration_type' => 2])->whereMonth('start_time|end_time', $days)->sum('duration');

        return rounding($dayNum + $duraNum / 8);
    }

    public function getCreateTimeAttr($val)
    {
        if(!$val) return '';
        return date('Y-m-d H:i:s', $val);
    }
}